#coding:utf-8
'''
* coder  : dzlua
* email  : 505544956@qq.com
* module : Flask-AuthMgr
* path   : tests
* file   : base.py
* time   : 2017-11-03 17:59:09
'''
#--------------------#
import unittest, base64
from flask import Flask, g, jsonify
from flask_auth_mgr import AuthMgr
#--------------------#

#--------------------#
class TestBase(unittest.TestCase):
    def setUp(self):
        app = Flask(__name__)
        app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy dog'
        auth = AuthMgr(app.config['SECRET_KEY'])
        #
        self.app = app
        self.auth = auth
        self.client = app.test_client()
        #
        self.initAuth(app, auth)
        self.initAuthSet(app, auth)
        self.initAuthUsers(app, auth)
        self.initAuthVerify(app, auth)
        self.initAuthAddRoutes(app, auth)
        self.initAuthErrorHandler(app, auth)
    def initAuth(self, app, auth):
        self.expires_in = None
        self.error_responds = 'Unauthorized Access'
        self.users = {}
        self.tokens = { 'refresh_token': {},'access_token': {}, 'user_token': {} }
    def initAuthSet(self, app, auth):
        pass
    def initAuthVerify(self, app, auth):
        @auth.verify_password
        def verify_password(user, pwd):
            g.user = None
            if user not in self.users:
                return False
            if auth.check_password(self.users.get(user), pwd):
                g.user = user
                return True
            return False

        @auth.verify_refresh_token
        def verify_rftoken(token):
            data = auth.refresh_token_data(token)
            if data is None:
                return False
            g.user = data['user']
            return True

        @auth.verify_access_token
        def verify_atoken(token):
            data = auth.access_token_data(token)
            if data is None:
                return False
            g.user = data['user']
            return True

        @auth.verify_user_token
        def verify_utoken(token):
            data = auth.user_token_data(token)
            if data is None:
                return False
            g.email = data['email']
            return True
    def initAuthUsers(self, app, auth):
        self.users["john"] = auth.decode_password("johnpassword")
        self.users["susan"] = auth.decode_password("susanpassword")
    def initAuthAddRoutes(self, app, auth):
        @app.route('/refresh_token')
        @auth.required_login
        def route_refresh_token():
            token_data = {
                'user': g.user,
            }

            data = {
                'refresh_token': auth.generate_refresh_token(token_data, self.expires_in),
            }
            return jsonify(data)

        @app.route('/access_token')
        @auth.required_refresh_token
        def route_access_token():
            token_data = {
                'user': g.user,
            }

            data = {
                'access_token': auth.generate_access_token(token_data, self.expires_in),
            }
            return jsonify(data)

        # rftoken -> rftoken
        @app.route('/token')
        @auth.required_multi_refresh
        def route_token():
            token_data = {
                'user': g.user,
            }

            data = {
                'refresh_token': auth.generate_refresh_token(token_data, self.expires_in),
                'access_token': auth.generate_access_token(token_data, self.expires_in),
            }
            return jsonify(data)

        @app.route('/user_token')
        def route_user_token():
            token_data = {
                'email': '505544956@qq.com'
            }

            data = {
                'user_token': auth.generate_user_token(token_data, self.expires_in)
            }
            return jsonify(data)
        #--------------------#
        @app.route('/need_pwd')
        @auth.required_login
        def route_need_pwd():
            return g.user

        @app.route('/need_rftoken')
        @auth.required_refresh_token
        def route_need_rftoken():
            return g.user

        @app.route('/need_pwd_rftoken')
        @auth.required_multi_refresh
        def route_need_pwd_rftoken():
            return g.user

        @app.route('/need_atoken')
        @auth.required_access_token
        def route_need_atoken():
            return g.user

        @app.route('/need_pwd_atoken')
        @auth.required_multi_access
        def route_need_pwd_atoken():
            return g.user

        @app.route('/need_utoken')
        @auth.required_user_token
        def route_need_utoken():
            return g.email
    def initAuthErrorHandler(self, app, auth):
        pass
    def headersPassword(self, user, pwd):
        txt = base64.b64encode('%s:%s' % (user, pwd))
        return { 'Authorization': 'Basic %s' % txt }
    def headersToken(self, token):
        return { 'Authorization': 'Bearer %s' % token }
    def get(self, api, token=None, user='susan', pwd='susanpassword'):
        if not token:
            headers = self.headersPassword(user, pwd)
        else:
            headers = self.headersToken(token)
        response = self.client.get(
            api,
            headers=headers )
        return response.data
    def gettoken(self):
        res = self.get('token', None)
        token = eval(res)
        self.assertNotEqual(token, self.error_responds)
        self.assertIn('refresh_token', token)
        self.assertIn('access_token', token)
        return token
    def getutoken(self):
        res = self.get('user_token', None)
        utoken = eval(res)
        self.assertNotEqual(utoken, self.error_responds)
        self.assertIn('user_token', utoken)
        return utoken
    def verifyRfToken(self, token, user):
        return False
    def verifyAToken(self, token, user):
        return False
    def verifyUToken(self, token, user):
        return False
    #----------#
    def CheckRfToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('refresh_token', token, user, pwd)
        if res == self.error_responds:
            return False
        token = eval(res)
        if 'refresh_token' not in token:
            return False
        return self.verifyRfToken(token['refresh_token'], user)
    def CheckAToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('access_token', token, user, pwd)
        if res == self.error_responds:
            return False
        token = eval(res)
        if 'access_token' not in token:
            return False
        return self.verifyAToken(token['access_token'], user)
    def CheckToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('token', token, user, pwd)
        if res == self.error_responds:
            return False
        token = eval(res)
        if 'refresh_token' not in token:
            return False
        if 'access_token' not in token:
            return False
        if not self.verifyRfToken(token['refresh_token'], user):
            return False
        return self.verifyAToken(token['access_token'], user)
    def CheckUToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('user_token', token, user, pwd)
        if res == self.error_responds:
            return False
        token = eval(res)
        if 'user_token' not in token:
            return False
        return self.verifyUToken(token['user_token'], user)
    def CheckNeedPwd(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_pwd', token, user, pwd)
        return res == user
    def CheckNeedRfToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_rftoken', token, user, pwd)
        return res == user
    def CheckNeedPwdOrRfToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_pwd_rftoken', token, user, pwd)
        return res == user
    def CheckNeedAToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_atoken', token, user, pwd)
        return res == user
    def CheckNeedPwdOrAToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_pwd_atoken', token, user, pwd)
        return res == user
    def CheckNeedUToken(self, token=None, user='susan', pwd='susanpassword'):
        res = self.get('need_utoken', token, user, pwd)
        return res == '505544956@qq.com'
#--------------------#
